package com.jsmile.cloud.tradecenter.order;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jsmile.cloud.msgcenter.api.feign.PayOrderServiceApi;
import com.jsmile.cloud.msgcenter.api.req.ReqPayOrderRefund;
import com.jsmile.cloud.tradecenter.api.enums.RefundFlagEnum;
import com.jsmile.cloud.tradecenter.api.exception.TradeException;
import com.jsmile.cloud.tradecenter.api.req.*;
import com.jsmile.cloud.tradecenter.api.res.ResOrder;
import com.jsmile.cloud.tradecenter.api.res.ResOrderList;
import com.jsmile.cloud.tradecenter.order.factory.OrderCreateFactory;
import com.jsmile.cloud.tradecenter.order.model.Order;
import com.jsmile.cloud.tradecenter.order.model.OrderProduct;
import com.jsmile.cloud.tradecenter.order.repo.OrderProductRepository;
import com.jsmile.cloud.tradecenter.order.repo.OrderProductSearchRepository;
import com.jsmile.cloud.tradecenter.order.repo.OrderRepository;
import com.jsmile.cloud.tradecenter.order.repo.OrderSearchRepository;
import com.jsmile.mall.api.JSmileResult;
import com.jsmile.mall.cache.kit.SpringKit;

import cn.hutool.core.bean.BeanUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@AllArgsConstructor
public class OrderApplicationService {

    private final OrderRepository orderRepository;
    private final OrderSearchRepository orderSearchRepository;
    private final OrderProductRepository orderProductRepository;
    private final OrderProductSearchRepository orderProductSearchRepository;
    private final OrderCreateFactory orderCreateFactory;

    public ResOrderList preview(ReqOrderCreate reqOrderCreate) {
        return orderCreateFactory.preview(reqOrderCreate);
    }

    public void toPay(ReqPayOrder reqPayOrder) {
        List<Order> orders = orderSearchRepository.findByOrderNos(reqPayOrder.getOrderNos());
        orderCreateFactory.toPay(orders);
    }

    public ResOrderList create(ReqOrderCreate reqOrderCreate) {
        ResOrderList resOrderList = BeanUtil.toBean(reqOrderCreate, ResOrderList.class);
        List<Order> orders = orderCreateFactory.create(reqOrderCreate);
        orderRepository.saveBatch(orders);
        resOrderList.setOrders(orders.stream().map(x -> {
            ResOrder resOrder = BeanUtil.toBean(x, ResOrder.class);
            resOrder.setOrderNo(x.getId());
            return resOrder;
        }).collect(Collectors.toList()));
        return resOrderList;
    }

    // 支付成功
    public void paySuccess(ReqPayOrder reqOrderPay) {
        orderRepository.updateBatchById(reqOrderPay.getOrderNos().stream().map(orderNo -> {
            Order order = orderSearchRepository.findByOrderNo(orderNo);
            order.paySuccess(reqOrderPay.getPayType());
            return order;
        }).collect(Collectors.toList()));
    }

    // 完成订单
    public void finishOrder(ReqOrderFinish reqOrderFinish) {
        Order order = orderSearchRepository.findByOrderNo(reqOrderFinish.getOrderNo());
        order.finishOrder(reqOrderFinish);
        orderRepository.updateById(order);
    }

    public void deliveyOrder() {

    }

    public void cancelOrder(ReqOrderCancel reqOrderCancel) {
        Order order = orderSearchRepository.findByOrderNo(reqOrderCancel.getOrderNo());
        order.cancelOrder();
        orderRepository.updateById(order);
    }

    public void refund(ReqOrderRefund reqOrderRefund) {
        Order order = orderSearchRepository.findByOrderNo(reqOrderRefund.getOrderNo());
        List<OrderProduct> orderProducts = orderProductSearchRepository.findByRefundOrder(reqOrderRefund);
        long refundAmount = orderProducts.stream().mapToLong(OrderProduct::getActuallyPayAmount).sum();
        JSmileResult jSmileResult =
            SpringKit.getBean(PayOrderServiceApi.class).refund(ReqPayOrderRefund.builder().refundAmount(refundAmount).orderNo(reqOrderRefund.getOrderNo()).build());
        if (!jSmileResult.getResSuccess()) {
            throw new TradeException("退款失败，请稍后重试!");
        }
        if (reqOrderRefund.getHasAllRefund() || order.getActuallyPayAmount().longValue() == refundAmount) {
            order.refund();
            orderRepository.updateById(order);
        }
        orderProducts.forEach(e -> {
            e.setRefundFlag(RefundFlagEnum.REFUND.getValue());
            e.setRefundTime(new Date());
        });
        orderProductRepository.updateBatchById(orderProducts);
    }

    public IPage<ResOrder> findAll(ReqOrderQuery reqOrderQuery) {
        return orderSearchRepository.findAll(reqOrderQuery).convert(x -> {
            return BeanUtil.toBean(x, ResOrder.class);
        });
    }

    public ResOrder findBySimpleOrderNo(ReqOrderDetail reqOrderDetail) {
        Order order = orderSearchRepository.findBySimpleOrderNo(reqOrderDetail.getOrderNo());
        ResOrder resOrder = BeanUtil.toBean(order, ResOrder.class);
        return resOrder;
    }

    public ResOrder findByOrderNo(ReqOrderDetail reqOrderDetail) {
        Order order = orderSearchRepository.findByOrderNo(reqOrderDetail.getOrderNo());
        ResOrder resOrder = BeanUtil.toBean(order, ResOrder.class);
        return resOrder;
    }
}
